/****************************************************************************/
/*                                                                          */
/*   FILE:    phystat.c														*/
/*   DATE:    31/07/97                                                      */
/*   PURPOSE: DVB-CI Physical layer - state diagram for PHYSICAL task       */  
/*   TAB STOPS : 4															*/
/*   HISTORY:				                                    			*/
/*   Version	Date	  	    Written by	     Notes	    	   			*/
/*	 1.0	    31/07/1997      SCM              Initial implementation 	*/
/*	 1.02		15/09/1997		SCM         	 Memory management			*/
/*		- PHYSICAL_connected() : if a LPDU can't be sent, the allocated		*/
/*				memory witch contains it is released						*/
/*                                                                    	    */
/*--------------------------------------------------------------------------*/
/*   GENERAL COMMENTS                                                 	    */
/*																		    */
/****************************************************************************/
#include <stdio.h>
#include <memory.h>
#include "sm_trace.h"
#include "itc.h"
#include "physical.h"
#include "phydrv.h"
#include "camusb.h"

/*--------------------------------------------------------------------------*/
/* External Variables		                                            	*/
/*--------------------------------------------------------------------------*/
extern physlot_t	g_phy_tab_slot[]; /* slot table   								*/


/* ======================================================================== */
/* NAME : PHYSICAL_Action					 								*/
/* 									    									*/
/* DESCRIPTION : Activate the action associated to the current state 		*/
/* 									    									*/
/* INPUT PARAMETERS :							    						*/
/*		index :		instance of the current state diagram					*/
/*		xmsgType :		current event (transition)								*/
/*		info :		conditionnal information according to the event			*/
/*									 										*/
/* RETURN CODE								    							*/
/*		1 : Success															*/
/*		0 : Error															*/
/*									  										*/
/* ======================================================================== */
int PHYSICAL_Action(int index, xmsg_t* pXmsg)			    
{
	int iRet;			/* return code 				*/

	SM_TRACE_ENTRY(TRMOD_PHY, "PHYSICAL_Action() - entry,index=%d,xmsgType=%s(0x%02X),"
				"curstate=%s(%d)\r\n", 
				index, XMSG_NAME(pXmsg->m_type), pXmsg->m_type,
				GETPHYSTATENAME(g_phy_tab_slot[index].m_state), 
				g_phy_tab_slot[index].m_state);

	switch(g_phy_tab_slot[index].m_state) 
	{
	case PHY_CONNECTED :
		/*a module is present in this slot*/
		iRet = PHYSICAL_Connected(index, pXmsg);
		break;
			
	case PHY_IDLE :
		/*no module is inserted in the physical slot*/
		iRet = PHYSICAL_Idle(index, pXmsg);
		break;

	default : 
		SM_TRACE_ERROR(TRMOD_PHY, "PHYSICAL_Action() - Unknown state %d\r\n", 
						g_phy_tab_slot[index].m_state);
		iRet = 0;
		break;
	}

	SM_TRACE_RETURN(TRMOD_PHY, "PHYSICAL_Action() - return,index=%d,"
				"xmsgType=%s(0x%02X),curstate=%s(%d),iRet=%d\r\n", 
				index, XMSG_NAME(pXmsg->m_type), pXmsg->m_type, 
				GETPHYSTATENAME(g_phy_tab_slot[index].m_state), 
				g_phy_tab_slot[index].m_state,
				iRet);
	return iRet;	
}

                                                                          
/* ======================================================================== */
/* NAME : PHYSICAL_Idle						 								*/
/* 									    									*/
/* DESCRIPTION : Execute the action of the idle state						*/
/*		There is a new DVB module inserted . The PHYSICAL layer sends the	*/
/*		connection indication to the LINK layer								*/
/* 									    									*/
/* INPUT PARAMETERS :							    						*/
/*		index :		instance of the current state diagram					*/
/*		xmsgType :		current event (transition)								*/
/*		pXmsg :	pointer to parameters of the received event or NULL		*/
/*									 										*/
/* RETURN CODE								    							*/
/*		1 : Success															*/
/*		0 : Error															*/
/*									  										*/
/* ======================================================================== */
int PHYSICAL_Idle(int index, xmsg_t* pXmsg)
{                                                                          
	int		iRet;
	xmsg_t	xmsg;

	SM_TRACE_ENTRY(TRMOD_PHY, "PHYSICAL_Idle() - entry,index=%d,xmsgType=%s(0x%02X),"
				"curstate=%s(%d)\r\n", 
				index, XMSG_NAME(pXmsg->m_type), pXmsg->m_type, 
				GETPHYSTATENAME(g_phy_tab_slot[index].m_state), 
				g_phy_tab_slot[index].m_state);

	switch(pXmsg->m_type)
	{
	case PH_INSERT: //send LN_CONNECT to the Link Task
		SM_TRACE_INFO(TRMOD_PHY, "PHYSICAL_Idle() - received PH_INSERT\r\n");
		memset(&xmsg, 0x00, sizeof(xmsg));
		xmsg.m_sndrcver	= (PHYSICAL << 4) | LINK;
		xmsg.m_type     = LN_CONNECT;
		xmsg.m_bd.m_ln_connect.m_slotId= g_phy_tab_slot[index].m_slotId;
		xmsg.m_bd.m_ln_connect.m_status = pXmsg->m_bd.m_ph_insert.m_status;
		xmsg.m_bd.m_ln_connect.m_negoSize = pXmsg->m_bd.m_ph_insert.m_negoSize;
    
		SM_TRACE_INFO(TRMOD_PHY, "PHYSICAL_Idle() - will send LN_CONNECT from PHYCIAL to LINK\r\n");
    	if (!ITC_SendXmsg(&xmsg))
    	{
			SM_TRACE_ERROR(TRMOD_PHY, "PHYSICAL_Idle() - Can't send the LN_CONNECT for %d slot to LINK Task\r\n", g_phy_tab_slot[index].m_slotId);
			iRet = 0;
		}
		else
		{
			SM_TRACE_INFO(TRMOD_PHY, "PHYSICAL_Idle() - set state to PHY_CONNECTED, index=%d\r\n", index);
			g_phy_tab_slot[index].m_state = PHY_CONNECTED; //Set the new state
			iRet = 1;
		}
		break;

	default :	// protocol error, ignore the event
		SM_TRACE_ERROR(TRMOD_PHY, "PHYSICAL_Idle() - ignore event %d received in %d state\r\n", pXmsg->m_type, g_phy_tab_slot[index].m_state);
		iRet = 0;
		break;			
	}

	SM_TRACE_RETURN(TRMOD_PHY, "PHYSICAL_Idle() - return,index=%d,"
				"xmsgType=%s(0x%02X),curstate=%s(%d),iRet=%d\r\n", 
				index, XMSG_NAME(pXmsg->m_type), pXmsg->m_type, 
				GETPHYSTATENAME(g_phy_tab_slot[index].m_state), 
				g_phy_tab_slot[index].m_state,
				iRet);
	return iRet;
}	/* end of PHY_IDLE state */
	

/* ======================================================================== */
/* NAME : PHYSICAL_Connected						 						*/
/* 									    									*/
/* DESCRIPTION : Execute the action of the PHY_CONNECTED state					*/
/*		- Receive LPDU from LINK task, send it to the PHYSICAL Driver and	*/
/*			send a LN_ACK acknowledge to the LNIK Task						*/
/*		- Receive event from PHYSICAL Driver and send it to the LINK Task	*/
/*			(Ex : LPDU)														*/
/* 									    									*/
/* INPUT PARAMETERS :							    						*/
/*		index :		instance of the current state diagram					*/
/*		xmsgType :		current event (transition)								*/
/*		pXmsg :	pointer to parameters of the received event or NULL		*/
/*									 										*/
/* RETURN CODE								    							*/
/*		1 : Success															*/
/*		0 : Error															*/
/*									  										*/
/* ======================================================================== */
int PHYSICAL_Connected(int index, xmsg_t* pXmsg)
{                                                                          
	int		iRet;
	xmsg_t	xmsg;

	SM_TRACE_ENTRY(TRMOD_PHY, "PHYSICAL_Connected() - entry,index=%d,xmsgType=%s(0x%02X),"
				"curstate=%s(%d)\r\n", 
				index, XMSG_NAME(pXmsg->m_type), pXmsg->m_type, 
				GETPHYSTATENAME(g_phy_tab_slot[index].m_state), 
				g_phy_tab_slot[index].m_state);

	iRet = 1;
	
	switch(pXmsg->m_type)
	{
	case LPDU: //send LPDU to the PHYSICAL Driver
		iRet = PHYS_DRVWrite(g_phy_tab_slot[index].m_slotId, 
								pXmsg->m_bd.m_lpdu.m_pbLpdu, 
								pXmsg->m_bd.m_lpdu.m_len);
		if (! iRet) //LPDU sent : send a LN_ACK to the LINK Task
		{
			memset(&xmsg, 0x00, sizeof(xmsg));
			xmsg.m_sndrcver		= (PHYSICAL << 4) | LINK;
			xmsg.m_type     	= LN_ACK;
			xmsg.m_bd.m_ln_ack.m_slotId= g_phy_tab_slot[index].m_slotId;
    
			/* Send the message */
    		if (!ITC_SendXmsg(&xmsg))
    		{
				SM_TRACE_ERROR(TRMOD_PHY, "PHYSICAL_Connected() - Can't send the LN_ACK for %d slot to LINK Task\r\n", g_phy_tab_slot[index].m_slotId);
				iRet = 0;		/* Error */
			}
			else
			{
				iRet = 1;		/* Success */
			}
		}
		else
		{
			/* Don't change the state */
			iRet = 0;		/* Error */
		}
		break;

	case PH_DATA: //send LPDU to the Link Task
		memset(&xmsg, 0x00, sizeof(xmsg));
		xmsg.m_bd.m_lpdu.m_pbLpdu = ITC_DynAlloc(pXmsg->m_bd.m_ph_data.m_len);
		if (xmsg.m_bd.m_lpdu.m_pbLpdu == NULL)
		{
			SM_TRACE_ERROR(TRMOD_PHY, "PHYSICAL_Connected() - can't allocate buffer for coding LPDU\r\n");
			return 0;
		}

		xmsg.m_sndrcver	= (PHYSICAL << 4) | LINK;
		xmsg.m_type     	= LPDU;
		xmsg.m_bd.m_lpdu.m_slotId = g_phy_tab_slot[index].m_slotId;
		xmsg.m_bd.m_lpdu.m_len     = pXmsg->m_bd.m_ph_data.m_len;
		memcpy(xmsg.m_bd.m_lpdu.m_pbLpdu, 
				pXmsg->m_bd.m_ph_data.m_pbData, 
				pXmsg->m_bd.m_ph_data.m_len);
    
    	if (!ITC_SendXmsg(&xmsg))
    	{
			FreeXmsg(&xmsg);
			SM_TRACE_ERROR(TRMOD_PHY, "PHYSICAL_Connected() - Can't send the LPDU for %d slot to LINK Task\r\n", g_phy_tab_slot[index].m_slotId);
			iRet = 0;
		}
		break;

	case PH_ERROR: //send LN_ERROR to the Link Task
		memset(&xmsg, 0x00, sizeof(xmsg));
		xmsg.m_sndrcver	= (PHYSICAL << 4) | LINK;
		xmsg.m_type     = LN_ERROR;
		xmsg.m_bd.m_ln_error.m_slotId= g_phy_tab_slot[index].m_slotId;
		xmsg.m_bd.m_ln_error.m_status= pXmsg->m_bd.m_ph_error.m_status;	//modify by pmy
		    
   		if (!ITC_SendXmsg(&xmsg))
   		{
			SM_TRACE_ERROR(TRMOD_PHY, "PHYSICAL_Connected() - Can't send the LN_ERROR for %d slot to LINK Task\r\n", g_phy_tab_slot[index].m_slotId);
			iRet = 0;
		}
		break;

	case PH_EXTRACT: //send LN_DISCONNECT to the Link Task
		memset(&xmsg, 0x00, sizeof(xmsg));
		xmsg.m_sndrcver	= (PHYSICAL << 4) | LINK;
		xmsg.m_type     = LN_DISCONNECT;
		xmsg.m_bd.m_ln_disconn.m_slotId= g_phy_tab_slot[index].m_slotId;
    
   		if (!ITC_SendXmsg(&xmsg))
   		{
			SM_TRACE_ERROR(TRMOD_PHY, "PHYSICAL_Connected() - Can't send the LN_DISCONNECT for %d slot to LINK Task\r\n", g_phy_tab_slot[index].m_slotId);
			iRet = 0;
		}
		else
		{
			g_phy_tab_slot[index].m_state = PHY_IDLE; //Set the new state
			iRet = 1;
		}
		break;

	default:	// protocol error, ignore the event
		SM_TRACE_ERROR(TRMOD_PHY, "PHYSICAL_Connected() - ignore event %d received in %d state\r\n", pXmsg->m_type, g_phy_tab_slot[index].m_state);
		iRet = 0;
		break;			
	}

	SM_TRACE_RETURN(TRMOD_PHY, "PHYSICAL_Connected() - return,index=%d,"
				"xmsgType=%s(0x%02X),curstate=%s(%d),iRet=%d\r\n", 
				index, XMSG_NAME(pXmsg->m_type), pXmsg->m_type,
				GETPHYSTATENAME(g_phy_tab_slot[index].m_state), 
				g_phy_tab_slot[index].m_state,
				iRet);
	return iRet;
}

int PHYSICAL_CurrentStatus(int index)
{
	int i = 0;
	int ret = 0;
	if (index < 0 || index >= MAXSLOTID)
	{
		return FALSE;
	}
	if (PHY_CONNECTED == g_phy_tab_slot[index].m_state)
	{
		return TRUE;
	}
	else
	{
		return FALSE;
	}
}






